package com.example.foo.admin.web.ftt;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtils;
import com.example.core.PageResult;
import com.example.core.Pageable;
import com.example.foo.UserLevelEnum;
import com.example.foo.ftt.FttLevel;
import com.example.foo.ftt.model.FttUser;
import com.example.foo.ftt.query.FttUserQuery;
import com.example.foo.ftt.service.FttUserFacadeService;
import com.example.foo.ftt.service.FttUserService;
import com.example.foo.p.service.FttRegisterService;
import com.example.support.redis.RedisHelper;

@org.springframework.web.bind.annotation.RestController
public class FttUserAction {

	private final FttUserService fttUserService;
	private final FttUserFacadeService fttUserFacadeService;
	private final FttRegisterService fttRegisterService;

	public FttUserAction(FttUserService fttUserService,
			FttUserFacadeService fttUserFacadeService,
			FttRegisterService fttRegisterService) {
		this.fttUserService = fttUserService;
		this.fttUserFacadeService = fttUserFacadeService;
		this.fttRegisterService = fttRegisterService;
	}

	@GetMapping("/api/fttusers")
	public AjaxResult index(FttUserQuery fttUserQuery, Pageable pageable) {
		PageResult<FttUser> pageResult = fttUserService.findFttUsers(fttUserQuery, pageable);
		List<FttUserVO> fttUserVOs = pageResult.getRows()
				.stream()
				.map(FttUserVO::new)
				.collect(Collectors.toList());
		return AjaxResult.successData(new PageResult<>(fttUserVOs, pageResult.getTotal()));
	}

	@GetMapping("/api/fttusers/export")
	public AjaxResult export(FttUserQuery fttUserQuery) {
		Pageable pageable = new Pageable(1, 65535);
		PageResult<FttUser> pageResult = fttUserService.findFttUsers(fttUserQuery, pageable);

		List<FttUserVO> fttUserVOs = pageResult.getRows()
				.stream()
				.map(FttUserVO::new)
				.collect(Collectors.toList());

		Map<String, String> fields = new LinkedHashMap<>();
		fields.put("ID", "id");
		fields.put("创建时间", "createdAt");
		fields.put("状态", "state");
		fields.put("角色", "roleLevel");
		fields.put("角色T", "roleLevelText");
		fields.put("网体级别", "fttLevel");
		fields.put("网体级别T", "fttLevelText");
		fields.put("手机号", "cellphone");
		fields.put("推荐码", "referralCode");
		fields.put("推荐上级用户ID", "referralParentUserId");
		fields.put("推荐上级用户ID路径", "referralParentUserIdPath");
		fields.put("上级用户ID", "parentUserId");
		fields.put("上级用户ID路径", "parentUserIdPath");
		fields.put("userId", "userId");
		fields.put("备注", "memo");
		fields.put("身份证姓名", "idname");
		fields.put("中军卡状态", "cardzState");
		fields.put("中军卡手机号", "cardzCellphone");
		return new ExcelUtils<>(FttUserVO.class).export(fields, fttUserVOs);
	}

	@GetMapping("/api/fttusers/{id}")
	public AjaxResult showFttUser(@PathVariable("id") Long id) {
		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}
		return AjaxResult.successData(new FttUserVO(fttUser));
	}

	@PostMapping("/api/fttusers")
	public AjaxResult createFttUser(FttUser fttUserForm) {
		//
		String cellphone = fttUserForm.getCellphone();
		Long referralParentUserId = fttUserForm.getReferralParentUserId();

		//
		if (StringUtils.isBlank(cellphone)) {
			return AjaxResult.error(400, "cellphone must not be null");
		}
		if (referralParentUserId == null) {
			return AjaxResult.error(400, "referralParentUserId must not be null");
		}

		//
		FttUser fttUser = fttUserService.findFttUserByCellphone(cellphone);
		if (fttUser != null) {
			return AjaxResult.error(400, "手机号已注册");
		}

		//
		FttUser referralParentFttUser = fttUserService.findFttUserByUserId(referralParentUserId);
		if (referralParentFttUser == null) {
			return AjaxResult.error(400, "referralParentUserId must not be exists");
		}

		//
		fttRegisterService.createFttUserRegisterByCellphone(cellphone, referralParentFttUser);

		return AjaxResult.success();
	}

	@PutMapping("/api/fttusers/{id}/state")
	public AjaxResult updateFttUserState(@PathVariable("id") Long id, FttUser fttUserForm) {
		FttUser.State state = fttUserForm.getState();
		String memo = fttUserForm.getMemo();
		if (state == null) {
			return AjaxResult.error(400, "state must not be null");
		}
		if (StringUtils.isBlank(memo)) {
			return AjaxResult.error(400, "memo must not be null");
		}

		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}

		fttUserFacadeService.updateFttUserState(id, state, memo);

		if (state == FttUser.State.banned) {
			clearToken(fttUser.getUserId());
		}

		return AjaxResult.success();
	}

	@PutMapping("/api/fttusers/{id}/rolelevel")
	public AjaxResult updateFttUserRoleLevel(@PathVariable("id") Long id, FttUser fttUserForm) {
		String roleLevel = fttUserForm.getRoleLevel();
		if (roleLevel == null) {
			return AjaxResult.error(400, "roleLevel must not be null");
		}

		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}

		fttUserService.updateFttUserRoleLevel(id, UserLevelEnum.ofLevelId(roleLevel));

		return AjaxResult.success();
	}

	@PutMapping("/api/fttusers/{id}/fttlevel")
	public AjaxResult updateFttUserFttLevel(@PathVariable("id") Long id, FttUser fttUserForm) {
		FttLevel fttLevel = fttUserForm.getFttLevel();
		if (fttLevel == null) {
			return AjaxResult.error(400, "fttLevel must not be null");
		}

		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}

		fttUserService.updateFttUserFttLevel(id, fttLevel);

		return AjaxResult.success();
	}

	@PutMapping("/api/fttusers/{id}/cellphone")
	public AjaxResult updateFttUserCellphone(@PathVariable("id") Long id, FttUser fttUserForm) {
		String cellphone = fttUserForm.getCellphone();
		if (cellphone == null) {
			return AjaxResult.error(400, "cellphone must not be null");
		}

		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}

		fttRegisterService.updateFttUserCellphone(id, cellphone);

		return AjaxResult.success();
	}

	@PutMapping("/api/fttusers/{id}/parents")
	public AjaxResult updateFttUserParents(@PathVariable("id") Long id, FttUser fttUserForm) {
		Long parentUserId = fttUserForm.getParentUserId();
		if (parentUserId == null) {
			return AjaxResult.error(400, "parentUserId must not be null");
		}

		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}

		fttUserFacadeService.updateFttUserParents(id, parentUserId);

		return AjaxResult.success();
	}

	@PutMapping("/api/fttusers/{id}/cardz")
	public AjaxResult updateFttUserCardz(@PathVariable("id") Long id, FttUser fttUserForm) {
		FttUser.CardzState cardzState = fttUserForm.getCardzState();
		String cardzCellphone = fttUserForm.getCardzCellphone();
		if (cardzState == null) {
			return AjaxResult.error(400, "cardzState must not be null");
		}
		if (StringUtils.isBlank(cardzCellphone)) {
			return AjaxResult.error(400, "cardzCellphone must not be null");
		}

		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}

		fttUserService.updateFttUserCardz(id, cardzState, cardzCellphone);

		return AjaxResult.success();
	}

	@DeleteMapping("/api/fttusers/{id}")
	public AjaxResult deleteFttUser(@PathVariable("id") Long id) {
		FttUser fttUser = fttUserService.findFttUserById(id);
		if (fttUser == null) {
			return AjaxResult.error(404, "Not Found");
		}
		fttRegisterService.deleteFttUserCascadeById(id);
		clearToken(fttUser.getUserId());
		return AjaxResult.success();
	}

	private void clearToken(Long userId) {
		Set<String> keys = RedisHelper.stringRedisTemplate().keys( String.format("token:%s.*", userId) );
		RedisHelper.stringRedisTemplate().delete(keys);
	}

}
